package com.dstz.form.rest.controller;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dstz.base.api.aop.annotion.CatchErr;
import com.dstz.base.api.exception.BusinessError;
import com.dstz.base.api.exception.BusinessException;
import com.dstz.base.api.query.QueryFilter;
import com.dstz.base.api.response.impl.ResultMsg;
import com.dstz.base.core.util.AppUtil;
import com.dstz.base.core.util.StringUtil;
import com.dstz.base.core.util.ThreadMapUtil;
import com.dstz.base.dao.CommonDao;
import com.dstz.base.db.datasource.DbContextHolder;
import com.dstz.base.db.model.page.PageResult;
import com.dstz.base.rest.ControllerTools;
import com.dstz.base.rest.util.RequestUtil;
import com.dstz.bus.api.constant.BusinessPermissionObjType;
import com.dstz.bus.api.model.IBusinessColumn;
import com.dstz.bus.api.model.IBusinessObject;
import com.dstz.bus.api.model.IBusinessPermission;
import com.dstz.bus.api.model.IBusinessTable;
import com.dstz.bus.api.service.IBusinessDataService;
import com.dstz.bus.api.service.IBusinessObjectService;
import com.dstz.bus.api.service.IBusinessPermissionService;
import com.dstz.bus.api.service.IBusinessTableService;
import com.dstz.form.api.constant.FormStatusCode;
import com.dstz.form.manager.FormCustSqlRelationManager;
import com.dstz.form.manager.FormDefManager;
import com.dstz.form.model.FormDef;
import com.dstz.form.model.FormDefData;
import com.dstz.form.service.FormDefDataService;
import com.dstz.form.util.tableexcel.BusinessTableExcellor;
import com.dstz.sys.api.groovy.IGroovyScriptEngine;
import com.dstz.sys.api.model.ISysDataSource;
import com.dstz.sys.api.service.ISysDataSourceService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;

/**
 * <pre>
 * 描述：表单数据的controller
 * 作者:aschs
 * 邮箱:aschs@qq.com
 * 日期:2018年5月17日
 * 版权:summer
 * </pre>
 */
@RestController
@RequestMapping("/form/formDefData/")
public class FormDefDataController extends ControllerTools {
	@Autowired
	FormDefDataService formDefDataService;
	@Autowired
	IBusinessDataService businessDataService;
	@Autowired
	IBusinessObjectService businessObjectService;
	@Autowired
	ISysDataSourceService sysDataSourceService;
	@Autowired
	CommonDao<?> commonDao;
	@Autowired
	IBusinessPermissionService businessPermissionService;
	@Autowired
	FormDefManager formDefManager;
	@Autowired
	IBusinessTableService businessTableService;
	@Autowired
	FormCustSqlRelationManager formCustSqlRelationManager;
	@Autowired
	IGroovyScriptEngine groovyScriptEngine;

	/**
	 * <pre>
	 * 获取FormDefData的后端
	 * </pre>
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("getData")
	@CatchErr(write2response = true, value = "获取FormDefData异常")
	public ResultMsg<FormDefData> getFormDefData(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String key = RequestUtil.getString(request, "key");
		String id = RequestUtil.getString(request, "id", null);
		boolean isSql = RequestUtil.getBoolean(request, "sql", false);
		ThreadMapUtil.put("FormDefDataController_getFormDefData_isSql", isSql);
		Boolean isReadOnly = RequestUtil.getBoolean(request, "isReadOnly", false);
		FormDefData formDefData = formDefDataService.getByFormDefKey(key, id, isReadOnly);
		return getSuccessResult(formDefData);
	}

	/**
	 * <pre>
	 * 保存formDef中的data数据
	 * </pre>
	 * 
	 * @param request
	 * @param response
	 * @param data
	 * @throws Exception
	 */
	@RequestMapping("saveData")
	@CatchErr(write2response = true, value = "保存formDef中的data数据异常")
	public ResultMsg<String> saveData(HttpServletRequest request, HttpServletResponse response, @RequestBody JSONObject data) throws Exception {
		String key = RequestUtil.getString(request, "key");
		boolean isSql = RequestUtil.getBoolean(request, "sql", false);
		formDefDataService.saveFormDefData(data, key, isSql);
		return getSuccessResult("保存数据成功");
	}

	/**
	 * <pre>
	 * 获取bo的数据列表
	 * </pre>
	 * 
	 * @param request
	 * @param response
	 * @param key
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("getList_{boKey}")
	@CatchErr(write2response = true, value = "获取对话框的列表数据失败")
	public PageResult getList(HttpServletRequest request, HttpServletResponse response, @PathVariable(value = "boKey") String boKey) throws Exception {
		QueryFilter queryFilter = getQueryFilter(request);
		// 页面来的参数
		IBusinessObject businessObject = businessObjectService.getFilledByKey(boKey);
		IBusinessTable businessTable = businessObject.getRelation().getTable();
		ISysDataSource sysDataSource = sysDataSourceService.getByKey(businessTable.getDsKey());
		// 切换数据源
		DbContextHolder.setDataSource(sysDataSource.getKey(), sysDataSource.getDbType());
		String sql = "select * from " + businessTable.getName();
		List<?> list = commonDao.queryForListPage(sql, queryFilter);
		return new PageResult(list);
	}

	@RequestMapping("removeData/{formKey}/{id}")
	@CatchErr(write2response = true, value = "删除formDef中的data数据异常")
	public ResultMsg removeData(@PathVariable(value = "formKey", required = false) String formKey, @PathVariable(value = "id", required = false) String id) throws Exception {
		if (StringUtil.isEmpty(formKey)) {
			throw new BusinessException("formKey 不能为空", FormStatusCode.PARAM_ILLEGAL);
		}
		if (StringUtil.isEmpty(id)) {
			throw new BusinessException("ID 不能为空", FormStatusCode.PARAM_ILLEGAL);
		}

		FormDef formDef = formDefManager.getByKey(formKey);
		String boKey = formDef.getBoKey();

		IBusinessPermission permission = businessPermissionService.getByObjTypeAndObjVal(BusinessPermissionObjType.FORM.getKey(), formKey, formDef.getBoKey(), true);
		IBusinessObject businessObject = businessObjectService.getFilledByKey(boKey);
		businessObject.setPermission(permission.getBusObj(boKey));

		if("DEMO".equalsIgnoreCase(AppUtil.getCtxEnvironment())){
         	throw new BusinessError("演示环境，禁止删除操作！<br/>您的访问信息已经被我们统计！");
        }
		
		businessDataService.removeData(businessObject, id);

		return getSuccessResult("删除成功！");
	}

	/**
	 * <pre>
	 * 表单导入excel
	 * </pre>
	 * 
	 * @param file
	 * @return
	 */
	@RequestMapping(value = "importExcel", method = RequestMethod.POST)
	@CatchErr(value = "excel导入失败")
	public ResultMsg<List<Map<String, Object>>> importExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "tableKey") String tableKey) throws Exception {
		ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
		List<Map<String, Object>> readAll = reader.readAll();
		IBusinessTable table = businessTableService.getFilledByKey(tableKey);
		return getSuccessResult(new BusinessTableExcellor(table).fromExcel(readAll));
	}

	/**
	 * <pre>
	 * 表单导出excel
	 * </pre>
	 * 
	 * @param file
	 * @return
	 */
	@RequestMapping(value = "exportExcel", method = RequestMethod.POST)
	@CatchErr(value = "excel导出失败")
	public void exportExcel(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "list") String listStr, @RequestParam(value = "tableKey") String tableKey, @RequestParam(value = "columnKeys") String columnKeys) throws Exception {
		IBusinessTable table = businessTableService.getFilledByKey(tableKey);
		JSONArray list = JSONArray.parseArray(listStr);

		ExcelWriter writer = ExcelUtil.getWriter();
		List<Map<String, Object>> dataList = new BusinessTableExcellor(table).toExcel(list);
		// 1 获取列名
		String[] lmKeys = columnKeys.split(",");
		List<String> lmNames = new ArrayList<>();
		for (String lk : lmKeys) {
			IBusinessColumn column = table.getColumnByKey(lk);
			if (column != null) {
				lmNames.add(column.getComment());
				writer.addHeaderAlias(column.getKey(), column.getComment());
			} else {
				lmNames.add(lk);
				writer.addHeaderAlias(lk, lk);
			}
		}
		if (list.isEmpty()) {// 空内容则需要手动写表头达到生成模板的效果
			writer.writeHeadRow(lmNames);
		}
		// 2 写内容
		List<Map<String, Object>> dl = new ArrayList<>();
		dataList.forEach(data -> {
			Map<String, Object> d = new LinkedHashMap<>();// 记得是有序map
			for (String lk : lmKeys) {
				d.put(lk, data.get(lk));
			}
			dl.add(d);
		});
		writer.write(dl);

		// 3 输出文件
		String downloadFileName = new String(table.getComment().getBytes("UTF-8"), "iso-8859-1");
		response.setContentType("application/vnd.ms-excel;charset=utf-8");
		response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName + ".xls");
		OutputStream out = response.getOutputStream();
		writer.flush(out);
		// 关闭writer，释放内存
		writer.close();
		// 此处记得关闭输出Servlet流
		IoUtil.close(out);
	}

	public static void main(String[] args) {
		Map<String, Object> row1 = new LinkedHashMap<>();
		row1.put("name", "张三");
		row1.put("examDate", DateUtil.date());
		row1.put("age", 23);
		row1.put("score", 88.32);
		row1.put("isPass", true);

		ArrayList<Map<String, Object>> rows = CollUtil.newArrayList(row1);
		// 通过工具类创建writer
		ExcelWriter writer = ExcelUtil.getWriter("d:/writeMapTest.xls");
		// 自定义标题别名
		writer.addHeaderAlias("name", "姓名");
		writer.addHeaderAlias("age", "年龄");
		writer.addHeaderAlias("score", "分数");
		writer.addHeaderAlias("isPass", "是否通过");
		writer.addHeaderAlias("examDate", "考试时间");
		// 合并单元格后的标题行，使用默认标题样式
		writer.merge(row1.size() - 1, "一班成绩单");
		// 一次性写出内容，使用默认样式，强制输出标题
		writer.write(rows);
		// 关闭writer，释放内存
		writer.close();
	}

	@RequestMapping("getDate")
	@CatchErr(write2response = true, value = "获取FormDefData异常")
	public ResultMsg<List<FormDefData>> getFormDef(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String key = RequestUtil.getString(request, "key");
		String id = RequestUtil.getString(request, "id", null);
		String num[]=id.split(",");
		boolean isSql = RequestUtil.getBoolean(request, "sql", false);
		ThreadMapUtil.put("FormDefDataController_getFormDefData_isSql", isSql);
		Boolean isReadOnly = RequestUtil.getBoolean(request, "isReadOnly", false);
		List<FormDefData> list=new ArrayList<FormDefData>();
		for (int i=0;i<num.length;i++){
			FormDefData formDefData = formDefDataService.getByFormDefKey(key, num[i], isReadOnly);
			list.add(formDefData);
		}
		return getSuccessResult(list);
	}
}
